﻿using System;
using System.Collections.Generic;
using System.Reflection;
using System.Text;
using Core.Model;
using Dapper;
using DapperExtensions;
using DapperExtensions.Mapper;
using log4net;

namespace DataServer.Dao
{
    public class RightDao : BaseDao<Right>
    {
        private readonly ILog _log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
        private static RightMapper _mapper;

        public RightDao()
        {
            if (_mapper == null)
            {
                _mapper = new RightMapper();
            }
        }

        protected override string GetTableName()
        {
            if (_mapper != null)
                return _mapper.TableName;
            return "right_info";
        }

        public Right GetEntityById(string id)
        {
            ConnectResult result = null;
            try
            {
                result = OpenDbConnection();
                var predicate = Predicates.Field<Right>(f => f.Id, Operator.Eq, id);
                Right right = result?.Connection.Get<Right>(predicate);
                return right;
            }
            catch (Exception ex)
            {
                _log.Error(ex.Message);
                return null;
            }
            finally
            {
                if (result != null)
                {
                    CloseDbConnection(result.Name);
                }
            }
        }

        public List<Right> GetUserRights(string userId)
        {
            if (string.IsNullOrEmpty(userId)) return new List<Right>();
            ConnectResult result = null;
            try
            {
                result = OpenDbConnection();
                List<Right> rights = result?.Connection.GetList<Right>($"select a.* from {GetTableName()} a,(SELECT * from user_right where UserId='{userId}') b where a.Id=b.RightId");
                return rights;
            }
            catch (Exception ex)
            {
                _log.Error(ex.Message);
                return null;
            }
            finally
            {
                if (result != null)
                {
                    CloseDbConnection(result.Name);
                }
            }
        }

        public bool UpdateUserRights(string userId,List<string> rightIds)
        {
            if (rightIds == null || string.IsNullOrEmpty(userId)) return false;
            ConnectResult result = null;
            try
            {
                result = OpenDbConnection();
                result?.Connection.Execute($"delete from user_right where UserId='{userId}'");
                if (rightIds.Count > 0)
                {
                    StringBuilder stringBuilder = new StringBuilder();
                    stringBuilder.Append("Insert Into user_right(Id,UserId,RightId) Values ");
                    foreach (string rightId in rightIds)
                    {
                        stringBuilder.Append($"('{Guid.NewGuid().ToString()}','{userId}','{rightId}'),");
                    }
                    stringBuilder.Remove(stringBuilder.Length - 1, 1);
                    result?.Connection.Execute(stringBuilder.ToString());
                }
                return true;
            }
            catch (Exception ex)
            {
                _log.Error(ex.Message);
                return false;
            }
            finally
            {
                if (result != null)
                {
                    CloseDbConnection(result.Name);
                }
            }
        }

        public List<string> GetUserDeviceIds(string userId)
        {
            if (string.IsNullOrEmpty(userId)) return new List<string>();
            ConnectResult result = null;
            try
            {
                result = OpenDbConnection();
                List<string> deviceIds = result?.Connection.GetList<string>($"SELECT DeviceId from user_device where UserId='{userId}'");
                return deviceIds;
            }
            catch (Exception ex)
            {
                _log.Error(ex.Message);
                return null;
            }
            finally
            {
                if (result != null)
                {
                    CloseDbConnection(result.Name);
                }
            }
        }

        public bool UpdateUserDevices(string userId, List<string> deviceIds)
        {
            if (deviceIds == null || string.IsNullOrEmpty(userId)) return false;
            ConnectResult result = null;
            try
            {
                result = OpenDbConnection();
                result?.Connection.Execute($"delete from user_device where UserId='{userId}'");
                if (deviceIds.Count > 0)
                {
                    StringBuilder stringBuilder = new StringBuilder();
                    stringBuilder.Append("Insert Into user_device(Id,UserId,DeviceId) Values ");
                    foreach (string rightId in deviceIds)
                    {
                        stringBuilder.Append($"('{Guid.NewGuid().ToString()}','{userId}','{rightId}'),");
                    }
                    stringBuilder.Remove(stringBuilder.Length - 1, 1);
                    result?.Connection.Execute(stringBuilder.ToString());
                }
                return true;
            }
            catch (Exception ex)
            {
                _log.Error(ex.Message);
                return false;
            }
            finally
            {
                if (result != null)
                {
                    CloseDbConnection(result.Name);
                }
            }
        }

        public bool UserOwnDevice(string userId, string devId)
        {
            if (string.IsNullOrEmpty(devId) || string.IsNullOrEmpty(userId)) return false;
            ConnectResult result = null;
            try
            {
                result = OpenDbConnection();
                
                object res = result?.Connection.ExecuteScalar($"select count(*) from user_device where UserId='{userId}' and DeviceId='{devId}'");
                if (res is int val)
                {
                    if (val > 0)
                        return true;
                }

                return false;
            }
            catch (Exception ex)
            {
                _log.Error(ex.Message);
                return false;
            }
            finally
            {
                if (result != null)
                {
                    CloseDbConnection(result.Name);
                }
            }
        }

        public Right GetEntityByName(string name)
        {
            ConnectResult result = null;
            try
            {
                result = OpenDbConnection();
                var predicate = Predicates.Field<Right>(f => f.Name, Operator.Eq, name);
                Right right = result?.Connection.Get<Right>(predicate);
                return right;
            }
            catch (Exception ex)
            {
                _log.Error(ex.Message);
                return null;
            }
            finally
            {
                if (result != null)
                {
                    CloseDbConnection(result.Name);
                }
            }
        }
    }
    public sealed class RightMapper : ClassMapper<Right>
    {
        public RightMapper()
        {
            Table("right_info");
            Map(x => x.Id).Key(KeyType.Assigned);
            //Ignore this property entirely
            //optional, map all other columns
            AutoMap();
        }
    }
}
